home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Periodicals / develop / develop 8 code / Curves in Quickdraw / QD Curves / curves.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-09  |  7.4 KB  |  338 lines  |  [TEXT/KAHL]

  1. #include <ToolUtils.h>
  2. #include <Memory.h>
  3. #include <QuickDraw.h>
  4. #include <FixMath.h>
  5.  
  6. #include "curves.h"
  7.  
  8. int OnCurve(long* bits, long index)
  9. {
  10.     bits += index >> 5;
  11.     index &= 31;
  12.     return (*bits & (0x80000000 >> index)) == 0;
  13. }
  14.  
  15. void FrameCurve(curve* cur, int level)
  16. {
  17.     if (level)
  18.     {    curve left, right;
  19.  
  20.         left.start = cur->start;
  21.         left.control.x = AVE(cur->start.x, cur->control.x);
  22.         left.control.y = AVE(cur->start.y, cur->control.y);
  23.         right.control.x = AVE(cur->control.x, cur->end.x);
  24.         right.control.y = AVE(cur->control.y, cur->end.y);
  25.         left.end.x = right.start.x = AVE(left.control.x, right.control.x);
  26.         left.end.y = right.start.y = AVE(left.control.y, right.control.y);
  27.         right.end = cur->end;
  28.  
  29.         FrameCurve( &left, level-1 );
  30.         FrameCurve( &right, level-1 );
  31.     }
  32.     else
  33.         flineto( cur->end.x, cur->end.y );
  34. }
  35.  
  36. path* NextPath(path* aPath)
  37. {
  38.     return (path*)((long*)aPath + 1 + (aPath->vectors + 31 >> 5) + aPath->vectors * 2);
  39. }
  40.  
  41. void InitPathWalker( pathWalker* w, path* aPath )
  42. {
  43.     w->index = 0;
  44.     w->ep = aPath->vectors - 1;
  45.     w->bits = aPath->controlBits;
  46.     /*
  47.      *    skip past the control bits to point to the first point
  48.      */
  49.     w->p = (point*)(w->bits + (aPath->vectors + 31 >> 5));
  50. }
  51.  
  52. int NextPathSegment( pathWalker* w)
  53. {
  54.     long prevIndex, nextIndex;
  55.  
  56.     /* 0 means this is the first segment */
  57.     if (w->index == 0)
  58.     {    if (OnCurve(w->bits, w->ep))
  59.             w->c.start = w->p[w->ep];
  60.         else
  61.         {    if (OnCurve(w->bits,0))
  62.             {    w->c.start = w->p[0];
  63.                 w->index = 1;
  64.             }
  65.             else    /* start at an implied on-curve point */
  66.             {    w->c.start.x = AVE(w->p[0].x, w->p[w->ep].x);
  67.                 w->c.start.y = AVE(w->p[0].y, w->p[w->ep].y);
  68.             }
  69.         }
  70.     }
  71.     else    /* start where we previously left off */
  72.         w->c.start = w->c.end;
  73.  
  74. NEXT_SEGMENT:
  75.     /*
  76.      *    compute the point index before and after the current one.
  77.      *    This wraps around, since we assume the contour is closed.
  78.      */
  79.     prevIndex = w->index == 0 ? w->ep : w->index - 1;
  80.     nextIndex = w->index  == w->ep ? 0 : w->index + 1;
  81.  
  82.     if (OnCurve(w->bits, w->index))
  83.     {    if (OnCurve(w->bits, prevIndex))
  84.         {    w->isLine = true;    /* this means we have a line */
  85.             w->c.end = w->p[w->index];
  86.         }
  87.         else if (w->index++ <= w->ep)
  88.             goto NEXT_SEGMENT;
  89.     }
  90.     else
  91.     {    w->isLine = false;        /* this means we have a curve */
  92.         w->c.control = w->p[w->index];
  93.         if (OnCurve(w->bits, nextIndex))
  94.             w->c.end = w->p[nextIndex];
  95.         else
  96.         {    w->c.end.x = AVE(w->p[w->index].x, w->p[nextIndex].x);
  97.             w->c.end.y = AVE(w->p[w->index].y, w->p[nextIndex].y);
  98.         }
  99.     }
  100.  
  101.     return w->index++ <= w->ep;    /* return true if there are still more segments */
  102. }
  103.  
  104. path* FramePath(path* cont, int closed)
  105. {
  106.     pathWalker walker;
  107.  
  108.     InitPathWalker(&walker, cont);
  109.     /*
  110.      *    The first segment is special, since it calls fmoveto.
  111.      */
  112.     if (NextPathSegment(&walker))
  113.     {    fmoveto( walker.c.start.x, walker.c.start.y );
  114.         if (walker.isLine)
  115.             flineto(walker.c.end.x, walker.c.end.y );
  116.         else
  117.             FrameCurve(&walker.c, kCurveLimit);
  118.     }
  119.     /*
  120.      *    Keep looping until we run out of segments
  121.      */
  122.     while (NextPathSegment(&walker))
  123.         if (walker.isLine)
  124.             flineto(walker.c.end.x, walker.c.end.y );
  125.         else
  126.             FrameCurve(&walker.c, kCurveLimit);
  127.  
  128.     /*
  129.      *    Return the next path, used if this path is one of several within a paths.
  130.      */
  131.     return NextPath(cont);
  132. }
  133.  
  134. void FramePaths(paths* aPath, int closed)
  135. {
  136.     long ctr = aPath->contours;
  137.     path* cont = aPath->contour;
  138.  
  139.     while (ctr--)
  140.         cont = FramePath( cont, closed );
  141. }
  142.  
  143. void PaintDiamond(Rect* r)
  144. {
  145.     short size = sizeof(short) + sizeof(Rect) + sizeof(Point) * 4;
  146.     PolyHandle p = (PolyHandle)NewHandle( size );
  147.     short* pt;
  148.  
  149.     p = OpenPoly();
  150.     MoveTo( r->right + r->left >> 1, r->top - 1 );
  151.     LineTo( r->right , r->top + r->bottom >> 1 );
  152.     LineTo( r->right + r->left >> 1, r->bottom );
  153.     LineTo( r->left - 1, r->top + r->bottom >> 1 );
  154.     ClosePoly();
  155.     PaintPoly(p);
  156.     KillPoly(p);
  157. }
  158.  
  159. void ExamplePaths()
  160. {
  161.     long myPaths[] = {
  162.         5,                /* 5 contours */
  163.         3, 0xE0000000, 0, ff(16), 0, ff(8), ff(14), ff(12),
  164.         3, 0xE0000000, ff(8), 0, ff(16), 0, ff(12), ff(14),
  165.         3, 0xE0000000, ff(24), ff(8), ff(24), ff(16), ff(10), ff(12),
  166.         3, 0xE0000000, ff(16), ff(24), ff(8), ff(24), ff(12), ff(10),
  167.         16, 0x11110000,
  168.                 ff(8), 0, ff(12), ff(4), ff(16), 0, ff(16), ff(8),
  169.                 ff(24), ff(8), ff(20), ff(12), ff(24), ff(16), ff(16), ff(16),
  170.                 ff(16), ff(24), ff(12), ff(20), ff(8), ff(24), ff(8), ff(16),
  171.                 0, ff(16), ff(4), ff(12), 0, ff(8), ff(8), ff(8)
  172.     };
  173.  
  174.     ScalePaths((paths*)myPaths, ff(15), ff(15));
  175.     OffsetPaths((paths*)myPaths, ff(25), ff(25));
  176.     FramePaths((paths*)myPaths, 0);
  177. }
  178.  
  179. void MarkPaths(paths* aPath)
  180. {
  181.     long ctr = aPath->contours;
  182.     path* cont = aPath->contour;
  183.     Point loc;
  184.     Rect r;
  185.  
  186.     while (ctr--)
  187.     {    long* bits = cont->controlBits;
  188.         long* coord = (long*)(bits + (cont->vectors + 31 >> 5));
  189.         long ptIndex;
  190.  
  191.         for (ptIndex = 0; ptIndex < cont->vectors; ptIndex++)
  192.         {    r.left = FR(*coord++) - 2;
  193.             r.top = FR(*coord++) - 2;
  194.             r.right = r.left + 5;
  195.             r.bottom = r.top + 5;
  196.             if (OnCurve(bits, ptIndex))
  197.                 PaintOval(&r);
  198. #if 1
  199.             else
  200.                 FillOval(&r, qd.gray);
  201. #endif
  202.         }
  203.         cont = (path*)coord;
  204.     }
  205. }
  206.  
  207. /*
  208.  *    Create a new path = dst + src, and then dispose dst.
  209.  */
  210. paths* AppendPaths(paths* dst, paths* src)
  211. {
  212.     long dstSize, srcSize = GetPtrSize((Ptr)src);
  213.     paths* newDst;
  214.  
  215.     if (dst)
  216.     {    dstSize = GetPtrSize((Ptr)dst);
  217.         newDst = (paths*)NewPtr(dstSize + srcSize - 4);
  218.     }
  219.     else
  220.         newDst = (paths*)NewPtr(srcSize);
  221.  
  222.     if (!newDst || MemError())
  223.         Debugger();
  224.  
  225.     if (dst)
  226.     {    BlockMove((Ptr)dst, (Ptr)newDst, dstSize);
  227.         BlockMove((Ptr)src + 4, (Ptr)newDst + dstSize, srcSize - 4);
  228.         *(long*)newDst += *(long*)src;
  229.         DisposePaths(dst);
  230.     }
  231.     else
  232.         BlockMove((Ptr)src, (Ptr)newDst, srcSize);
  233.  
  234.     return newDst;
  235. }
  236.  
  237. void DisposePaths(paths* p)
  238. {
  239.     DisposPtr((Ptr)p);
  240. }
  241.  
  242. void GetPathsBounds(paths* p, Rect* r)
  243. {
  244.     long ctr = p->contours;
  245.     path* cont = p->contour;
  246.  
  247.     r->left = r->top = 32767;
  248.     r->right = r->bottom = -32678;
  249.  
  250.     while (ctr--)
  251.     {    long* bits = cont->controlBits;
  252.         long* coord = (long*)(bits + (cont->vectors + 31 >> 5));
  253.         long ptIndex;
  254.  
  255.         for (ptIndex = 0; ptIndex < cont->vectors; ptIndex++)
  256.         {    short x = FR(*coord++);
  257.             short y = FR(*coord++);
  258.  
  259.             if (x < r->left) r->left = x; else
  260.             if (x > r->right) r->right = x;
  261.             if (y < r->top) r->top = y; else
  262.             if (y > r->bottom) r->bottom = y;
  263.         }
  264.         cont = (path*)coord;
  265.     }
  266. }
  267.  
  268. void OffsetPaths( paths* p, Fixed dx, Fixed dy )
  269. {
  270.     long ctrs = p->contours;
  271.     path* aPath = p->contour;
  272.  
  273.     while (ctrs--)
  274.     {    long pts = aPath->vectors;
  275.         Fixed* coord = (Fixed*)aPath + 1 + (pts + 31 >> 5);
  276.         
  277.         while (pts--)
  278.         {    *coord++ += dx;
  279.             *coord++ += dy;
  280.         }
  281.         aPath = (path*)coord;
  282.     }
  283. }
  284.  
  285. void ScalePaths(paths* p, Fixed sx, Fixed sy)
  286. {
  287.     long ctrs = p->contours;
  288.     path* aPath = p->contour;
  289.  
  290.     while (ctrs--)
  291.     {    long pts = aPath->vectors;
  292.         Fixed* coord = (Fixed*)aPath + 1 + (pts + 31 >> 5);
  293.         
  294.         while (pts--)
  295.         {    *coord = FixMul(*coord, sx);
  296.             coord++;
  297.             *coord = FixMul(*coord, sy);
  298.             coord++;
  299.         }
  300.         aPath = (path*)coord;
  301.     }
  302. }
  303.  
  304. void MapPaths(paths* p, Rect* src, Rect* dst)
  305. {
  306.     Fixed sx = FixDiv( dst->right - dst->left, src->right - src->left );
  307.     Fixed sy = FixDiv( dst->bottom - dst->top, src->bottom - src->top );
  308.  
  309.     OffsetPaths(p, -ff(src->left), -ff(src->top));
  310.     ScalePaths(p, sx, sy);
  311.     OffsetPaths(p, ff(dst->left), ff(dst->top));
  312. }
  313.  
  314. long SizeOfPaths(paths* p)
  315. {
  316.     long size = sizeof(long);
  317.     long ctrs = p->contours;
  318.     path* cont = p->contour;
  319.  
  320.     while (ctrs--)
  321.     {    long pathSize = (1 + (cont->vectors + 31 >> 5) + (cont->vectors << 1)) << 2;
  322.  
  323.         size += pathSize;
  324.         cont = (path*)((Ptr)cont + pathSize);
  325.     }
  326.     return size;
  327. }
  328.  
  329. paths* CopyPaths(paths* p)
  330. {
  331.     long size = SizeOfPaths(p);
  332.     Ptr p2 = NewPtr( size );
  333.  
  334.     BlockMove( (Ptr)p, p2, size );
  335.     return (paths*)p2;
  336. }
  337.  
  338.